package com.ssy.lingxi.contract.serviceimpl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.contract.api.model.vo.request.PurchaseInviteBidAddVO;
import com.ssy.lingxi.contract.constant.Constants;
import com.ssy.lingxi.contract.entity.PurchaseInviteBidDO;
import com.ssy.lingxi.contract.entity.QPurchaseInviteBidDO;
import com.ssy.lingxi.contract.model.constant.CommonBooleanEnum;
import com.ssy.lingxi.contract.model.vo.common.request.PurchaseInviteBidPageVO;
import com.ssy.lingxi.contract.model.vo.common.response.PurchaseInviteBidQueryVO;
import com.ssy.lingxi.contract.repository.PurchaseInviteBidRepository;
import com.ssy.lingxi.contract.service.IFeignService;
import com.ssy.lingxi.contract.service.IPurchaseInviteBidService;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.message.api.vo.request.SystemMessageRequest;
import com.ssy.lingxi.report.api.enums.ContractManageOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 采购招标合同接口实现
 * @author 伍将
 * @date 2021/3/5
 * @version 2.0.0
 */
@Service
@Slf4j
public class PurchaseInviteBidServiceImpl implements IPurchaseInviteBidService {

    @Resource
    private PurchaseInviteBidRepository repository;

    @Resource
    JPAQueryFactory queryFactory;
    @Resource
    IFeignService feignService;

    /**
     * 分页查询待创建采购招标合同
     * @author 伍将
     * @date 2021/3/5
     * @param user: 当前登录用户
     * @param pageVO: 分页请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<PageData<PurchaseInviteBidQueryVO>> pageToBeCreate(UserLoginCacheDTO user, PurchaseInviteBidPageVO pageVO) {
        // 组装查询条件
        Specification<PurchaseInviteBidDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("inviteBidMemberId").as(Long.class), user.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("inviteBidRoleId").as(Long.class), user.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("isCreate").as(Long.class), CommonBooleanEnum.NO.getCode()));
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("bidWinnerNoticeTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("bidWinnerNoticeTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getInviteBidNO())) {
                list.add(criteriaBuilder.like(root.get("inviteBidNO").as(String.class), "%" + pageVO.getInviteBidNO().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getInviteBidAbstract())) {
                list.add(criteriaBuilder.like(root.get("inviteBidAbstract").as(String.class), "%" + pageVO.getInviteBidAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getBidNo())) {
                list.add(criteriaBuilder.like(root.get("bidNo").as(String.class), "%" + pageVO.getBidNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getBidWinnerName())) {
                list.add(criteriaBuilder.like(root.get("bidWinnerName").as(String.class), "%" + pageVO.getBidWinnerName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("bidWinnerNoticeTime").descending());

        Page<PurchaseInviteBidDO> result = repository.findAll(spec, page);
        List<PurchaseInviteBidQueryVO> resultList = result.getContent().stream().map(o -> {
            PurchaseInviteBidQueryVO entity = new PurchaseInviteBidQueryVO();
            entity.setId(o.getId());
            entity.setInviteBidMemberId(o.getInviteBidMemberId());
            entity.setInviteBidRoleId(o.getInviteBidRoleId());
            entity.setInviteBidId(o.getInviteBidId());
            entity.setInviteBidNO(o.getInviteBidNO());
            entity.setInviteBidAbstract(o.getInviteBidAbstract());
            entity.setInviteBidPublishTime(DateUtil.format(DateUtil.date(o.getInviteBidPublishTime()), "yyyy-MM-dd HH:mm"));
            entity.setBidId(o.getBidId());
            entity.setBidNo(o.getBidNo());
            entity.setBidWinnerMemberId(o.getBidWinnerMemberId());
            entity.setBidWinnerRoleId(o.getBidWinnerRoleId());
            entity.setBidWinnerName(o.getBidWinnerName());
            entity.setBidWinnerNoticeTime(DateUtil.format(DateUtil.date(o.getBidWinnerNoticeTime()), "yyyy-MM-dd HH:mm"));
            entity.setBidWinnerAmount(o.getBidWinnerAmount());
            entity.setOuterStatus("已完成");
            entity.setInnerStatus("已完成");
            return entity;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 批量新增采购招标合同
     * @author 伍将
     * @date 2021/3/5
     * @param addVOList: 新增请求参数
     * @return 操作结果
     **/
    @Override
    @Transactional
    public Wrapper<Void> addList(List<PurchaseInviteBidAddVO> addVOList) {
        log.info("批量新增采购招标合同addVOList:{}", JSONUtil.toJsonStr(addVOList));
        if (null != addVOList && addVOList.size() > 0) {

            // 验证新增数据是否已存在
            for (PurchaseInviteBidAddVO addVO : addVOList) {
                PurchaseInviteBidDO existEntity = repository.findData(addVO.getInviteBidMemberId(), addVO.getInviteBidRoleId(), addVO.getInviteBidId(), addVO.getBidWinnerMemberId(), addVO.getBidWinnerRoleId());
                if (null != existEntity) {
                    throw new BusinessException(ResponseCode.CONTRACT_PURCHASE_INVITE_BID_IS_EXIST);
                }
            }

            // 组装新增对象
            List<PurchaseInviteBidDO> addList = addVOList.stream().map(o -> {
                PurchaseInviteBidDO entity = new PurchaseInviteBidDO();
                entity.setInviteBidMemberId(o.getInviteBidMemberId());
                entity.setInviteBidRoleId(o.getInviteBidRoleId());
                entity.setInviteBidId(o.getInviteBidId());
                entity.setInviteBidNO(o.getInviteBidNO());
                //entity.setInviteBidAbstract(o.getInviteBidAbstract());
                entity.setInviteBidAbstract(o.getProjectName());
                entity.setInviteBidPublishTime(o.getInviteBidPublishTime());
                entity.setBidId(o.getBidId());
                entity.setBidNo(o.getBidNo());
                entity.setBidWinnerMemberId(o.getBidWinnerMemberId());
                entity.setBidWinnerRoleId(o.getBidWinnerRoleId());
                entity.setBidWinnerName(o.getBidWinnerName());
                entity.setBidWinnerNoticeTime(o.getBidWinnerNoticeTime());
                entity.setBidWinnerAmount(o.getBidWinnerAmount());
                entity.setInnerStatus(o.getInnerStatus());
                entity.setOuterStatus(o.getOuterStatus());
                entity.setIsCreate(CommonBooleanEnum.NO.getCode());
                entity.setCreateTime(System.currentTimeMillis());
                entity.setUpdateTime(System.currentTimeMillis());
                entity.setPurchaseType(o.getPurchaseType());
                return entity;
            }).collect(Collectors.toList());

            // 保存采购招标合同
            repository.saveAll(addList);
            //采购招标提交+系统操作通知
            List<OperateNoticeVO> noticeVOS = addList.stream().map(inquiry -> {
                OperateNoticeVO noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(inquiry.getInviteBidMemberId());
                noticeVO.setRoleId(inquiry.getInviteBidRoleId());
                noticeVO.setDataSource(OperateDataSourceEnum.CONTRACT_MANAGE.getCode());
                noticeVO.setIncreaseOperateType(ContractManageOperateTypeEnum.TO_BE_CREATE_INQUIRY.getCode());
                noticeVO.setIncreaseCount(Constants.SYS_OPERATE_NOTICE_COUNT);
                noticeVO.setIncreaseTitle(inquiry.getInviteBidAbstract());
                noticeVO.setIncreaseDataId(inquiry.getId());
                return noticeVO;
            }).collect(Collectors.toList());
            feignService.addSysOperateNoticeToMQ(noticeVOS);
            //发送消息
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCommit() {
                    List<SystemMessageRequest> msgList = addVOList.stream().map(o -> {
                        SystemMessageRequest request = new SystemMessageRequest();
                        request.setMemberId(o.getInviteBidMemberId());
                        request.setRoleId(o.getInviteBidRoleId());
                        request.setMessageNotice(MessageTemplateCode.contract_manage_bidding_create);
                        request.setParams(Stream.of(o.getInviteBidNO(), o.getInviteBidAbstract()).collect(Collectors.toList()));
                        return request;
                    }).collect(Collectors.toList());
                    feignService.batchSendSystemMessage(msgList);
                }
            });
        }

        return Wrapper.success();
    }

    /**
     * 检查采购报价合同是否已创建合同
     * @author 伍将
     * @date 2021/3/4
     * @param user: 当前登录用户
     * @param inviteBidId: 招标单id
     * @param bidWinnerMemberId: 中标会员id
     * @param bidWinnerRoleId: 中标会员角色id
     * @return 操作结果
     **/
    @Override
    public PurchaseInviteBidDO checkCreate(UserLoginCacheDTO user, Long inviteBidId, Long bidWinnerMemberId, Long bidWinnerRoleId) {

        PurchaseInviteBidDO entity = repository.findData(user.getMemberId(), user.getMemberRoleId(), inviteBidId, bidWinnerMemberId, bidWinnerRoleId);
        if (null == entity) {
            throw new BusinessException(ResponseCode.CONTRACT_PURCHASE_INVITE_BID_NOT_EXIST);
        }

        if (CommonBooleanEnum.YES.getCode().equals(entity.getIsCreate())) {
            throw new BusinessException(ResponseCode.CONTRACT_PURCHASE_INVITE_BID_IS_CREATE);
        }

        return entity;
    }

    private  PurchaseInviteBidDO findData(Long inviteBidMemberId, Long inviteBidRoleId, Long inviteBidId, Long bidWinnerMemberId, Long bidWinnerRoleId){
        QPurchaseInviteBidDO query= QPurchaseInviteBidDO.purchaseInviteBidDO;
        return queryFactory.select(query)
                    .from(query)
                    .where(query.inviteBidMemberId.eq(inviteBidMemberId),
                            query.inviteBidRoleId.eq(inviteBidRoleId),
                            query.inviteBidId.eq(inviteBidId),
                            query.bidWinnerMemberId.eq(bidWinnerMemberId),
                            query.bidWinnerRoleId.eq(bidWinnerRoleId))
                    .fetchFirst();
    }

    /**
     * 更新采购招标合同创建状态
     * @author 伍将
     * @date 2021/3/4
     * @param user: 当前登录用户
     * @param inviteBidId: 招标单id
     * @param bidWinnerMemberId: 中标会员id
     * @param bidWinnerRoleId: 中标会员角色id
     * @param isCreate 创建合同：0-否，1-是
     * @return 操作结果
     **/
    @Override
    public Wrapper<Void> updateCreateStatus(UserLoginCacheDTO user, Long inviteBidId, Long bidWinnerMemberId, Long bidWinnerRoleId, Integer isCreate) {
        PurchaseInviteBidDO entity = findData(user.getMemberId(), user.getMemberRoleId(), inviteBidId, bidWinnerMemberId, bidWinnerRoleId);
        if (null == entity) {
            throw new BusinessException(ResponseCode.CONTRACT_PURCHASE_INVITE_BID_NOT_EXIST);
        }

        if (CommonBooleanEnum.YES.getCode().equals(entity.getIsCreate()) && CommonBooleanEnum.YES.getCode().equals(isCreate)) {
            throw new BusinessException(ResponseCode.CONTRACT_PURCHASE_INVITE_BID_IS_CREATE);
        }

        entity.setIsCreate(isCreate);
        entity.setUpdateTime(System.currentTimeMillis());
        repository.saveAndFlush(entity);

        return Wrapper.success();
    }
}
